﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration.Install;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;

namespace Broadbeach.Service
{
    [RunInstaller(true)]
    public class Installer : System.Configuration.Install.Installer
    {
        public Installer()
        {
            var assembly = Assembly.GetExecutingAssembly();
            var productName = assembly
                .GetCustomAttributes(true)
                .OfType<AssemblyProductAttribute>()
                .Single().Product;
            
            var serviceInstaller = new ServiceInstaller
                                       {
                                           DisplayName = productName,
                                           ServiceName = assembly.GetName().Name,
                                           StartType = ServiceStartMode.Automatic,
                                           ServicesDependedOn = new[] {"HTTP"}
                                       };
            Installers.Add(serviceInstaller);

            var eventLogInstaller = serviceInstaller.Installers.OfType<EventLogInstaller>().Single();
            eventLogInstaller.Log = "Application";
            eventLogInstaller.Source = serviceInstaller.ServiceName;

            var processInstaller = new ServiceProcessInstaller();
            Installers.Add(processInstaller);
        }

        public static void Install(string username, string password)
        {
            var parameters = new NameValueCollection();
            if (!string.IsNullOrEmpty(username)) parameters.Add("username", username);
            if (!string.IsNullOrEmpty(password)) parameters.Add("password", password);
            RunInstaller(i => i.Install(new Hashtable()), parameters);
        }

        public static void Uninstall()
        {
            RunInstaller(i => i.Uninstall(null), new NameValueCollection()); // requires null.
        }

        private static void RunInstaller(Action<System.Configuration.Install.Installer> installerAction, NameValueCollection parameters)
        {
            using (var ti = new TransactedInstaller())
            using (var mi = new Installer())
            {
                ti.Installers.Add(mi);
                var path = String.Format("/assemblypath={0}", Assembly.GetExecutingAssembly().Location);
                var ctx = new InstallContext("", new[] { path });
                foreach (var paramName in parameters.AllKeys)
                {
                    ctx.Parameters.Add(paramName, parameters[paramName]);
                }
                ti.Context = ctx;
                installerAction(ti);
            }
        }
    }
}